"""
JSON 格式导入导出策略
"""
from __future__ import annotations

import json
from datetime import datetime
from pathlib import Path
from typing import Any, Dict, List

from ..domain import (
    ProjectSnapshot,
    ProjectMetadata,
    CategorySnapshot,
    ParameterSnapshot,
    ParameterValueSnapshot,
)
from .base import ExportStrategy, ImportStrategy, ExportResult


class JsonExportStrategy(ExportStrategy):
    """将项目快照导出为 JSON 文件"""

    @classmethod
    def get_format_info(cls) -> Dict[str, Any]:
        """获取 JSON 导出格式信息"""
        return {
            "format": "json",
            "name": "JSON文件",
            "extension": ".json",
            "description": "轻量级的JSON格式文件，适合程序处理和API调用"
        }

    def __init__(self, output_dir: Path = Path("exports")) -> None:
        self.output_dir = output_dir

    def export(self, snapshot: ProjectSnapshot) -> ExportResult:
        snapshot.ensure_export_time()
        self.output_dir.mkdir(parents=True, exist_ok=True)
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        filename = f"{snapshot.metadata.name_en}_parameters_{timestamp}.json"
        file_path = self.output_dir / filename

        payload = self._build_payload(snapshot)
        with file_path.open("w", encoding="utf-8") as f:
            json.dump(payload, f, ensure_ascii=False, indent=2)

        return ExportResult(file_path=file_path, mime_type="application/json")

    def get_diff_ignore_fields(self) -> List[str]:
        return []

    def _build_payload(self, snapshot: ProjectSnapshot) -> Dict[str, Any]:
        return {
            "project": {
                "id": snapshot.metadata.id,
                "name": snapshot.metadata.name,
                "name_en": snapshot.metadata.name_en,
                "description": snapshot.metadata.description,
                "time_horizon": snapshot.metadata.time_horizon,
                "start_year": snapshot.metadata.start_year,
                "year_step": snapshot.metadata.year_step,
                "end_year": snapshot.metadata.end_year,
                "export_time": snapshot.metadata.export_time.isoformat()
                if snapshot.metadata.export_time
                else None,
                "checksum": snapshot.metadata.checksum,
                "created_at": snapshot.metadata.created_at.isoformat()
                if snapshot.metadata.created_at
                else None,
                "updated_at": snapshot.metadata.updated_at.isoformat()
                if snapshot.metadata.updated_at
                else None,
            },
            "categories": [self._build_category(c) for c in snapshot.categories],
        }

    def _build_category(self, category: CategorySnapshot) -> Dict[str, Any]:
        return {
            "id": category.id,
            "name": category.name,
            "name_en": category.name_en,
            "description": category.description,
            "sort_order": category.sort_order,
            "created_at": category.created_at.isoformat()
            if category.created_at
            else None,
            "updated_at": category.updated_at.isoformat()
            if category.updated_at
            else None,
            "parameters": [self._build_parameter(p) for p in category.parameters],
        }

    def _build_parameter(self, parameter: ParameterSnapshot) -> Dict[str, Any]:
        return {
            "id": parameter.id,
            "name": parameter.name,
            "name_en": parameter.name_en,
            "param_type": parameter.param_type,
            "unit": parameter.unit,
            "description": parameter.description,
            "is_list": parameter.is_list,
            "is_year_related": parameter.is_year_related,
            "list_length": parameter.list_length,
            "sort_order": parameter.sort_order,
            "created_at": parameter.created_at.isoformat()
            if parameter.created_at
            else None,
            "updated_at": parameter.updated_at.isoformat()
            if parameter.updated_at
            else None,
            "values": [
                {
                    "id": value.id,
                    "index": value.index,
                    "value": value.value,
                    "created_at": value.created_at.isoformat()
                    if value.created_at
                    else None,
                    "updated_at": value.updated_at.isoformat()
                    if value.updated_at
                    else None,
                }
                for value in parameter.values
                if value.value is not None
            ],
        }


class JsonImportStrategy(ImportStrategy):
    """从 JSON 文件恢复项目快照"""

    @classmethod
    def get_format_info(cls) -> Dict[str, Any]:
        """获取 JSON 导入格式信息"""
        return {
            "format": "json",
            "name": "JSON文件",
            "extensions": [".json"],
            "description": "JSON数据格式文件"
        }

    def import_snapshot(self, input_path: Path) -> ProjectSnapshot:
        with input_path.open("r", encoding="utf-8") as f:
            payload = json.load(f)

        return ProjectSnapshot(
            metadata=self._parse_metadata(payload["project"]),
            categories=[
                self._parse_category(category_data)
                for category_data in payload.get("categories", [])
            ],
        )

    def get_diff_ignore_fields(self) -> List[str]:
        return []

    def _parse_metadata(self, project_data: Dict[str, Any]) -> ProjectMetadata:
        export_time = project_data.get("export_time")
        parsed_export_time = (
            datetime.fromisoformat(export_time) if export_time else None
        )
        return ProjectMetadata(
            name=project_data["name"],
            name_en=project_data["name_en"],
            description=project_data.get("description"),
            time_horizon=project_data["time_horizon"],
            start_year=project_data["start_year"],
            year_step=project_data["year_step"],
            end_year=project_data["end_year"],
            export_time=parsed_export_time,
            checksum=project_data.get("checksum"),
        )

    def _parse_category(self, category_data: Dict[str, Any]) -> CategorySnapshot:
        return CategorySnapshot(
            name=category_data["name"],
            name_en=category_data["name_en"],
            description=category_data.get("description"),
            sort_order=category_data.get("sort_order", 0),
            parameters=[
                self._parse_parameter(param_data)
                for param_data in category_data.get("parameters", [])
            ],
        )

    def _parse_parameter(self, param_data: Dict[str, Any]) -> ParameterSnapshot:
        values_data: List[Dict[str, Any]] = param_data.get("values", [])
        values = [
            ParameterValueSnapshot(
                index=value_data.get("index"),
                value=value_data.get("value"),
            )
            for value_data in values_data
        ]

        # 针对非列表参数，向后兼容旧结构
        if not param_data.get("is_list", False) and not values:
            single_value = param_data.get("value")
            values = [ParameterValueSnapshot(index=None, value=single_value)]

        return ParameterSnapshot(
            name=param_data["name"],
            name_en=param_data["name_en"],
            param_type=param_data["param_type"],
            unit=param_data.get("unit"),
            description=param_data.get("description"),
            is_list=param_data["is_list"],
            is_year_related=param_data["is_year_related"],
            list_length=param_data.get("list_length"),
            sort_order=param_data.get("sort_order", 0),
            values=values,
        )

